#include "Base.h"

void CDate::SetDate(int timeZone, int year, int month, int day, int hour, int minute)
{
	m_timeZone = timeZone;
	m_year = year;
	m_month = month;
	m_day = day;
	m_hour = hour;
	m_minute = minute;
}

void CClearSkyParameter::SetParameters(float a, float b, float c, float d, float e, float Lp)
{
	m_a = a;
	m_b = b;
	m_c = c;
	m_d = d;
	m_e = e;
	m_Lp = Lp;
}

void CClearSkyParameter::SetParameters(float para[])
{
	m_a = para[0];
	m_b = para[1];
	m_c = para[2];
	m_d = para[3];
	m_e = para[4];
	m_Lp = para[5];
}

void CPoint3D::SetPoint(float x, float y, float z)
{
	m_x = x;
	m_y = y;
	m_z = z;
}

void CPoint3D::Normalize()
{
	float length = sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
	m_x /= length;
	m_y /= length;
	m_z /= length;
}

int Date2Num(int year, int month, int day)
{
	int dayInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	int num = 0;
	for (int i = 0; i < month - 1; i++)
	{
		num += dayInMonth[i];
	}
	if (month > 2 && IS_LEAP_YEAR(year))
		num++;
	num += day;
	int leapYearNum = (year / 4 - year / 100 + year / 400) - (1899 / 4 - 1899 / 100 + 1899 / 400);
	num += 365 * (year - 1900) + leapYearNum;
	return num;
}

int Date2Num(CDate date)
{
	return Date2Num(date.m_year, date.m_month, date.m_day);
}

void Str2Char(CString str, char* pChar)
{
	int n = str.GetLength();
	int len = WideCharToMultiByte(CP_ACP, 0, str, str.GetLength(), NULL, 0, NULL, NULL);
	WideCharToMultiByte(CP_ACP, 0, str, str.GetLength() + 1, pChar, len + 1, NULL, NULL);
	pChar[len] = '\0';
}

bool CalcCoords(CPoint3D pInA, CPoint3D pInB, CPoint3D xInA, CPoint3D &yInA, CPoint3D &zInA)
{
	//	A: known coord
	//	B: unkonwn coord
	//	given the indices of a vector in coordA, coordB
	//	given the x coords in A
	//	compute y coord and z coord in A


	double m = pInB.m_y;
	double n1 = pInA.m_x;
	double n2 = pInA.m_y;
	double n3 = pInA.m_z;
	double x1 = xInA.m_x;
	double x2 = xInA.m_y;
	double x3 = xInA.m_z;
	double Q12 = x1 * n2 - x2 * n1;
	double Q23 = x2 * n3 - x3 * n2;
	double Q31 = x3 * n1 - x1 * n3;

	double A = Q12 * Q12 + Q23 * Q23 + Q31 * Q31;
	double B = 2 * (x1 * Q31 - x2 * Q23) * m;
	double C = (x1 * x1 + x2 * x2) * m * m - Q12 * Q12;
	double delta = B * B - 4 * A * C;
	double cos1 = (-B + sqrt(delta)) / (2 * A);
	double cos2 = (-B - sqrt(delta)) / (2 * A);
	//	consider cos1
	double theta = acos(cos1);
	double U = (x1 * m + Q31 * cos1) / Q12;
	double V = (-x2 * m + Q23 * cos1) / Q12;
	double phi = atan2(U, V);
	if (sin(phi) * U < 0)
		phi += M_PI;
	yInA.SetPoint(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
	zInA = Cross(xInA, yInA);
	if (abs(pInA.m_x * zInA.m_x + pInA.m_y * zInA.m_y + pInA.m_z * zInA.m_z - pInB.m_z) < EPS
		&& yInA.m_z < 0)
		return true;

	//	consider cos2
	theta = acos(cos2);
	U = (x1 * m + Q31 * cos2) / Q12;
	V = (-x2 * m + Q23 * cos2) / Q12;
	phi = atan2(U, V);
	if (sin(phi) * U < 0)
		phi += M_PI;
	yInA.SetPoint(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
	zInA = Cross(xInA, yInA);
	if (abs(pInA.m_x * zInA.m_x + pInA.m_y * zInA.m_y + pInA.m_z * zInA.m_z - pInB.m_z) < EPS
		&& yInA.m_z < 0)
		return true;
	return false;
}

CPoint3D Cross(CPoint3D u, CPoint3D v)
{
	CPoint3D w;
	w.SetPoint(
		u.m_y * v.m_z - u.m_z * v.m_y,
		u.m_z * v.m_x - u.m_x * v.m_z,
		u.m_x * v.m_y - u.m_y * v.m_x
	);
	return w;
}